package com.xyy.saas.payment.query.core.trade;

import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.bo.TransactionResultBO;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.cores.enums.TransactionStatusEnum;
import com.xyy.saas.payment.cores.param.TransactionParam;
import com.xyy.saas.payment.cores.vo.ResultVO;
import com.xyy.saas.payment.util.JSONUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractTransactionQuery implements TransactionQuery {
    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractTransactionQuery.class);

    public TransactionResultBO queryTransaction(TransactionParam param) throws PaymentException {
        LOGGER.info("AbstractTransactionQueryService#queryTransaction start param:{}", JSONUtils.toJSON(param));
        // 1. 参数校验
        ResultVO checkResult = checkParam(param);
        // LOGGER.info("AbstractTransactionQueryService#queryTransaction checkParam checkResult:{}, tradeNo:{}", JSONUtils.toJSON(checkResult), param.getTradeNo());
        if(checkResult.isFail()) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR, checkResult.getMsg());
        }
        // 2. 查本地
        // LOGGER.info("AbstractTransactionQueryService#queryTransaction isQueryLocalData:{}", param.isQueryLocalData());
        if(param.isQueryLocalData()) {
            LOGGER.info("AbstractTransactionQueryService#queryTransaction queryLocalRecord param:{}", JSONUtils.toJSON(param));
            TransactionResultBO resultBO = queryLocalRecord(param);
            LOGGER.info("AbstractTransactionQueryService#queryTransaction queryLocalRecord resultBO:{}", JSONUtils.toJSON(resultBO));
            // 是否查渠道 否则直接返回结果
            if(!checkIfQueryChannel(resultBO)) {
                // 是否给予业务补个回调
                if(param.isCallback()) {
                    LOGGER.info("AbstractTransactionQueryService#queryTransaction callback param:{}", JSONUtils.toJSON(resultBO));
                    callback(resultBO);
                }
                LOGGER.info("AbstractTransactionQueryService#queryTransaction return resultBO:{}", JSONUtils.toJSON(resultBO));
                return resultBO;
            }
        }

        // 查询渠道
        LOGGER.info("AbstractTransactionQueryService#queryTransaction queryChannelRecord param:{}", JSONUtils.toJSON(param));
        TransactionResultBO channelRecord = queryChannelRecord(param);
        LOGGER.info("AbstractTransactionQueryService#queryTransaction queryChannelRecord channelRecord:{}", JSONUtils.toJSON(channelRecord));

        // 处理渠道查询结果 -- 校验本地更新本地
        processChannelRecord(param, channelRecord);

        // 是否给予业务补个回调
        if(param.isCallback()) {
            LOGGER.info("AbstractTransactionQueryService#queryTransaction callback channelRecord:{}", JSONUtils.toJSON(channelRecord));
            callback(channelRecord);
        }

        // 返回，以渠道结果为准
        LOGGER.info("AbstractTransactionQueryService#queryTransaction return channelRecord:{}", JSONUtils.toJSON(channelRecord));
        return channelRecord;
    }


    // 回调业务
    protected void callback(TransactionResultBO resultBO) {
        LOGGER.info("AbstractTransactionQuery#callback nothing. TransactionResultBO:{}", JSONUtils.toJSON(resultBO));
    };
    // 处理渠道查询结果 -- 比较本地是否进行更新
    protected abstract void processChannelRecord(TransactionParam param, TransactionResultBO channelRecord) throws PaymentException;
    // 参数校验
    protected abstract ResultVO checkParam(TransactionParam param);
    // 查询本地记录
    protected abstract TransactionResultBO queryLocalRecord(TransactionParam param) throws PaymentException ;
    // 校验是否查询渠道
    protected abstract boolean checkIfQueryChannel(TransactionResultBO resultBO);
    // 查询渠道记录
    protected abstract TransactionResultBO queryChannelRecord(TransactionParam param) throws PaymentException ;

}
